#pragma once

#include "DXGIEnum.h"

namespace DX4WRT
{
	namespace DXGI
	{
		public ref class SwapChainDescription1 sealed
		{
			public:
				SwapChainDescription1 ()
				{
					m_Desc.Width = 0;
					m_Desc.Height = 0;
					m_Desc.Format = DXGI_FORMAT_UNKNOWN;
					m_Desc.Stereo = FALSE;
					m_Desc.SampleDesc.Count = 1;
					m_Desc.SampleDesc.Quality = 0;
					m_Desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
					m_Desc.BufferCount = 0;
					m_Desc.Scaling = DXGI_SCALING_NONE;
					m_Desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
					m_Desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
					m_Desc.Flags = 0;
				}
				~SwapChainDescription1 ()
				{
				}

				property uint32 Width {uint32 get() {return m_Desc.Width;} void set (uint32 value) {m_Desc.Width=value;}}
				property uint32 Height {uint32 get() {return m_Desc.Height;} void set (uint32 value) {m_Desc.Height=value;}}
				property DX4WRT::DXGI::Format Format {DX4WRT::DXGI::Format get() {return (DX4WRT::DXGI::Format)m_Desc.Format;}  void set (DX4WRT::DXGI::Format value) {m_Desc.Format=(DXGI_FORMAT)value;}}
				property bool Stereo {bool get() {return m_Desc.Stereo;} void set (bool value) {m_Desc.Stereo=value;}}
				property uint32 SampleCount {uint32 get() {return m_Desc.SampleDesc.Count;} void set (uint32 value) {m_Desc.SampleDesc.Count=value;}}
				property uint32 SampleQuality {uint32 get() {return m_Desc.SampleDesc.Quality;} void set (uint32 value) {m_Desc.SampleDesc.Quality=value;}}
				property DX4WRT::DXGI::Usage BufferUsage {DX4WRT::DXGI::Usage get() {return (DX4WRT::DXGI::Usage)m_Desc.BufferUsage;} void set (DX4WRT::DXGI::Usage value) {m_Desc.BufferUsage=(DXGI_USAGE)value;}}
				property uint32 BufferCount {uint32 get() {return m_Desc.BufferCount;} void set (uint32 value) {m_Desc.BufferCount=value;}}
				property DX4WRT::DXGI::Scaling Scaling {DX4WRT::DXGI::Scaling get() {return (DX4WRT::DXGI::Scaling)m_Desc.Scaling;} void set (DX4WRT::DXGI::Scaling value) {m_Desc.Scaling=(DXGI_SCALING)value;}}
				property DX4WRT::DXGI::SwapEffect SwapEffect {DX4WRT::DXGI::SwapEffect get() {return (DX4WRT::DXGI::SwapEffect)m_Desc.SwapEffect;} void set (DX4WRT::DXGI::SwapEffect value) {m_Desc.SwapEffect=(DXGI_SWAP_EFFECT)value;}}
				property DX4WRT::DXGI::AlphaMode AlphaMode {DX4WRT::DXGI::AlphaMode get() {return (DX4WRT::DXGI::AlphaMode)m_Desc.AlphaMode;} void set (DX4WRT::DXGI::AlphaMode value) {m_Desc.AlphaMode=(DXGI_ALPHA_MODE)value;}}
				property DX4WRT::DXGI::SwapChainOptions Flags {DX4WRT::DXGI::SwapChainOptions get() {return (DX4WRT::DXGI::SwapChainOptions)m_Desc.Flags;} void set (DX4WRT::DXGI::SwapChainOptions value) {m_Desc.Flags=(UINT)value;}}

			internal:
				DXGI_SWAP_CHAIN_DESC1 m_Desc;
		};

		public interface class IObject
		{
			public:
/*        virtual HRESULT STDMETHODCALLTYPE SetPrivateData( 
            _In_  REFGUID Name,
            UINT DataSize,
            _In_reads_bytes_(DataSize)  const void *pData) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE SetPrivateDataInterface( 
            _In_  REFGUID Name,
            _In_  const IUnknown *pUnknown) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetPrivateData( 
            _In_  REFGUID Name,
            _Inout_  UINT *pDataSize,
            _Out_writes_bytes_(*pDataSize)  void *pData) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetParent( 
            _In_  REFIID riid,
            _Out_  void **ppParent) = 0;*/
	    };


		public interface class IAdapter : public IObject
		{
			public:
				void GetInternal (Platform::IntPtr* pVal);

				property Platform::String^ Description {Platform::String^ get();}
				property uint32 VendorId {uint32 get();}
				property uint32 DeviceId {uint32 get();}
				property uint32 SubSysId {uint32 get();}
				property uint32 Revision {uint32 get();}
				property uint64 DedicatedVideoMemory {uint64 get();}
				property uint64 DedicatedSystemMemory {uint64 get();}
				property uint64 SharedSystemMemory {uint64 get();}
//				LUID AdapterLuid;
/*				virtual HRESULT STDMETHODCALLTYPE EnumOutputs( 
					UINT Output,
					_Out_  IDXGIOutput **ppOutput) = 0;
        
       
        virtual HRESULT STDMETHODCALLTYPE CheckInterfaceSupport( 
            _In_  REFGUID InterfaceName,
            _Out_  LARGE_INTEGER *pUMDVersion) = 0;*/
	    };

		public interface class IAdapter1 : public IAdapter
		{
			public:
				property AdapterOptions Flags {AdapterOptions get();}
		};

/* only Desktop
		public interface class IAdapter2 : public IAdapter1
		{
			public:
				virtual HRESULT STDMETHODCALLTYPE GetDesc2( 
				_Out_  DXGI_ADAPTER_DESC2 *pDesc) = 0;
		};
	*/

		public interface class IDevice : public IObject
		{
			public:
				/*virtual HRESULT STDMETHODCALLTYPE GetAdapter( 
            _Out_  IDXGIAdapter **pAdapter) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE CreateSurface( 
            _In_  const DXGI_SURFACE_DESC *pDesc,
            UINT NumSurfaces,
            DXGI_USAGE Usage,
            _In_opt_  const DXGI_SHARED_RESOURCE *pSharedResource,
            _Out_  IDXGISurface **ppSurface) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE QueryResourceResidency( 
            _In_reads_(NumResources)  IUnknown *const *ppResources,
            _Out_writes_(NumResources)  DXGI_RESIDENCY *pResidencyStatus,
            UINT NumResources) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE SetGPUThreadPriority( 
            INT Priority) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetGPUThreadPriority( 
            _Out_  INT *pPriority) = 0;*/
		};

	    public interface class IDevice1 : public IDevice
		{
			public:
/*		        virtual HRESULT STDMETHODCALLTYPE SetMaximumFrameLatency( 
				MaxLatency) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE GetMaximumFrameLatency( 
            _Out_  UINT *pMaxLatency) = 0;*/
		};

		public interface class IDevice2 : public IDevice1
		{
			public:
/*        virtual HRESULT STDMETHODCALLTYPE OfferResources( 
            _In_  UINT NumResources,
            _In_reads_(NumResources)  IDXGIResource *const *ppResources,
            _In_  DXGI_OFFER_RESOURCE_PRIORITY Priority) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE ReclaimResources( 
            _In_  UINT NumResources,
            _In_reads_(NumResources)  IDXGIResource *const *ppResources,
            _Out_writes_all_opt_(NumResources)  BOOL *pDiscarded) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE EnqueueSetEvent( 
            _In_  HANDLE hEvent) = 0;*/
		};

		public interface class IDeviceSubObject : public IObject
		{
			public:
/*				virtual HRESULT STDMETHODCALLTYPE GetDevice( 
					_In_  REFIID riid,
            _Out_  void **ppDevice) = 0;*/
		};

		public interface class IDisplayControl
		{
			public:
				/*virtual BOOL STDMETHODCALLTYPE IsStereoEnabled( void) = 0;
        
        virtual void STDMETHODCALLTYPE SetStereoEnabled( 
            BOOL enabled) = 0;*/
		};

		public interface class ISwapChain : public IDeviceSubObject
		{
			public:
				void GetInternal (Platform::IntPtr* pVal);

				void Present (uint32 syncInterval, PresentOptions flags);
/*
			virtual HRESULT STDMETHODCALLTYPE GetBuffer( 
				UINT Buffer,
				_In_  REFIID riid,
				_Out_  void **ppSurface) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetFullscreenState( 
				BOOL Fullscreen,
				_In_opt_  IDXGIOutput *pTarget) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFullscreenState( 
				_Out_opt_  BOOL *pFullscreen,
				_Out_opt_  IDXGIOutput **ppTarget) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetDesc( 
				_Out_  DXGI_SWAP_CHAIN_DESC *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE ResizeBuffers( 
				UINT BufferCount,
				UINT Width,
				UINT Height,
				DXGI_FORMAT NewFormat,
				UINT SwapChainFlags) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE ResizeTarget( 
				_In_  const DXGI_MODE_DESC *pNewTargetParameters) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetContainingOutput( 
				_Out_  IDXGIOutput **ppOutput) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics( 
				_Out_  DXGI_FRAME_STATISTICS *pStats) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetLastPresentCount( 
				_Out_  UINT *pLastPresentCount) = 0;*/
		};

		public interface class ISwapChain1 : public ISwapChain
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE GetDesc1( 
				_Out_  DXGI_SWAP_CHAIN_DESC1 *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFullscreenDesc( 
				_Out_  DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetHwnd( 
				_Out_  HWND *pHwnd) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetImmersiveWindow( 
				_In_  REFIID refiid,
				_Out_  void **ppUnk) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetCompositionSurface( 
				_Out_  HANDLE *pSurface) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE Present1( 
				UINT SyncInterval,
				UINT PresentFlags,
				_In_  const DXGI_PRESENT_PARAMETERS *pPresentParameters) = 0;
        
			virtual BOOL STDMETHODCALLTYPE IsTemporaryMonoSupported( void) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetRestrictToOutput( 
				_Out_  IDXGIOutput **ppRestrictToOutput) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetBackgroundColor( 
				_In_  const DXGI_RGBA *pColor) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetBackgroundColor( 
				_Out_  DXGI_RGBA *pColor) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetRotation( 
				_In_  DXGI_MODE_ROTATION Rotation) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetRotation( 
				_Out_  DXGI_MODE_ROTATION *pRotation) = 0;*/
		};

		public interface class IOutput : public IObject
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE GetDesc( 
				_Out_  DXGI_OUTPUT_DESC *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetDisplayModeList( 
				DXGI_FORMAT EnumFormat,
				UINT Flags,
				_Inout_  UINT *pNumModes,
				_Out_writes_to_opt_(*pNumModes,*pNumModes)  DXGI_MODE_DESC *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE FindClosestMatchingMode( 
				_In_  const DXGI_MODE_DESC *pModeToMatch,
				_Out_  DXGI_MODE_DESC *pClosestMatch,
				_In_opt_  IUnknown *pConcernedDevice) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE WaitForVBlank( void) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE TakeOwnership( 
				_In_  IUnknown *pDevice,
				BOOL Exclusive) = 0;
        
			virtual void STDMETHODCALLTYPE ReleaseOwnership( void) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetGammaControlCapabilities( 
				_Out_  DXGI_GAMMA_CONTROL_CAPABILITIES *pGammaCaps) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetGammaControl( 
				_In_  const DXGI_GAMMA_CONTROL *pArray) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetGammaControl( 
				_Out_  DXGI_GAMMA_CONTROL *pArray) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetDisplaySurface( 
				_In_  IDXGISurface *pScanoutSurface) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData( 
				_In_  IDXGISurface *pDestination) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFrameStatistics( 
				_Out_  DXGI_FRAME_STATISTICS *pStats) = 0;*/
		};

		public interface class IOutput1 : public IOutput
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE GetDisplayModeList1( 
				DXGI_FORMAT EnumFormat,
				UINT Flags,
				_Inout_  UINT *pNumModes,
				_Out_writes_to_opt_(*pNumModes,*pNumModes)  DXGI_MODE_DESC1 *pDesc);
        
			virtual HRESULT STDMETHODCALLTYPE FindClosestMatchingMode1( 
				_In_  const DXGI_MODE_DESC1 *pModeToMatch,
				_Out_  DXGI_MODE_DESC1 *pClosestMatch,
				_In_opt_  IUnknown *pConcernedDevice) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetDisplaySurfaceData1( 
				_In_  IDXGIResource *pDestination) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE DuplicateOutput( 
				_In_  IUnknown *pDevice,
				_Out_  IDXGIOutputDuplication **ppOutputDuplication) = 0;*/
		};

		public interface class IOutputDuplication : public IObject
		{
		public:
/*			virtual void STDMETHODCALLTYPE GetDesc( 
				_Out_  DXGI_OUTDUPL_DESC *pDesc) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE AcquireNextFrame( 
				_In_  UINT TimeoutInMilliseconds,
				_Out_  DXGI_OUTDUPL_FRAME_INFO *pFrameInfo,
				_Out_  IDXGIResource **ppDesktopResource) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFrameDirtyRects( 
				_In_  UINT DirtyRectsBufferSize,
				_Out_writes_bytes_to_(DirtyRectsBufferSize, *pDirtyRectsBufferSizeRequired)  RECT *pDirtyRectsBuffer,
				_Out_  UINT *pDirtyRectsBufferSizeRequired) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFrameMoveRects( 
				_In_  UINT MoveRectsBufferSize,
				_Out_writes_bytes_to_(MoveRectsBufferSize, *pMoveRectsBufferSizeRequired)  DXGI_OUTDUPL_MOVE_RECT *pMoveRectBuffer,
				_Out_  UINT *pMoveRectsBufferSizeRequired) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetFramePointerShape( 
				_In_  UINT PointerShapeBufferSize,
				_Out_writes_bytes_to_(PointerShapeBufferSize, *pPointerShapeBufferSizeRequired)  void *pPointerShapeBuffer,
				_Out_  UINT *pPointerShapeBufferSizeRequired,
				_Out_  DXGI_OUTDUPL_POINTER_SHAPE_INFO *pPointerShapeInfo) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE MapDesktopSurface( 
				_Out_  DXGI_MAPPED_RECT *pLockedRect) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE UnMapDesktopSurface( void) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE ReleaseFrame( void) = 0;*/
		};

		public interface class IFactory : public IObject
		{
		public:
			IAdapter^ EnumAdapters (uint32 adapter);
        
/*			virtual HRESULT STDMETHODCALLTYPE MakeWindowAssociation( 
				HWND WindowHandle,
				UINT Flags) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetWindowAssociation( 
				_Out_  HWND *pWindowHandle) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE CreateSwapChain( 
				_In_  IUnknown *pDevice,
				_In_  DXGI_SWAP_CHAIN_DESC *pDesc,
				_Out_  IDXGISwapChain **ppSwapChain) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE CreateSoftwareAdapter( 
				HMODULE Module,
				_Out_  IDXGIAdapter **ppAdapter) = 0;*/
		};

		public interface class IFactory1 : public IFactory
		{
			public:
				IAdapter1^ EnumAdapters1 (uint32 adapter);

				property bool IsCurrent
				{
					bool get();
				}
		};

		public interface class IFactory2 : public IFactory1
		{
			public:
				property bool IsWindowedStereoEnabled
				{
					bool get();
				}

				ISwapChain1^ CreateSwapChainForImmersiveWindow (IDevice^ device, Platform::Object^ window, SwapChainDescription1^ description, IOutput^ RestrictToOutput);
        
			/*virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd( 
				_In_  IUnknown *pDevice,
				_In_  HWND hWnd,
				_In_  const DXGI_SWAP_CHAIN_DESC1 *pDesc,
				_In_opt_  const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc,
				_In_opt_  IDXGIOutput *pRestrictToOutput,
				_Out_  IDXGISwapChain1 **ppSwapChain) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForCompositionSurface( 
				_In_  IUnknown *pDevice,
				_In_opt_  HANDLE hSurface,
				_In_  const DXGI_SWAP_CHAIN_DESC1 *pDesc,
				_In_opt_  IDXGIOutput *pRestrictToOutput,
				_Out_  IDXGISwapChain1 **ppSwapChain) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetSharedResourceAdapterLuid( 
				_In_  HANDLE hResource,
				_Out_  LUID *pLuid) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusWindow( 
				_In_  HWND WindowHandle,
				_In_  UINT wMsg,
				_Out_  DWORD *pdwCookie) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE RegisterStereoStatusEvent( 
				_In_  HANDLE hEvent,
				_Out_  DWORD *pdwCookie) = 0;
        
			virtual void STDMETHODCALLTYPE UnregisterStereoStatus( 
				_In_  DWORD dwCookie) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusWindow( 
				_In_  HWND WindowHandle,
				_In_  UINT wMsg,
				_Out_  DWORD *pdwCookie) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE RegisterOcclusionStatusEvent( 
				_In_  HANDLE hEvent,
				_Out_  DWORD *pdwCookie) = 0;
        
			virtual void STDMETHODCALLTYPE UnregisterOcclusionStatus( 
				_In_  DWORD dwCookie) = 0;*/
		};

		public interface class IKeyedMutex : public IDeviceSubObject
		{
/*			public:
        virtual HRESULT STDMETHODCALLTYPE AcquireSync( 
            UINT64 Key,
            DWORD dwMilliseconds) = 0;
        
        virtual HRESULT STDMETHODCALLTYPE ReleaseSync( 
            UINT64 Key) = 0;*/
		};

		public interface class IResource : public IDeviceSubObject
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE GetSharedHandle( 
				_Out_  HANDLE *pSharedHandle) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetUsage( 
				_Out_  DXGI_USAGE *pUsage) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE SetEvictionPriority( 
				UINT EvictionPriority) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE GetEvictionPriority( 
				_Out_  UINT *pEvictionPriority) = 0;*/
		};

		public interface class IResource1 : public IResource
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE CreateSubresourceSurface( 
				UINT index,
				_Out_  IDXGISurface2 **ppSurface) = 0;
        
			virtual HRESULT STDMETHODCALLTYPE CreateSharedHandle( 
				_In_opt_  const SECURITY_ATTRIBUTES *pAttributes,
				_In_  DWORD dwAccess,
				_In_opt_  LPCWSTR lpName,
				_Out_  HANDLE *pHandle) = 0;*/
		};

		public interface class ISurface : public IDeviceSubObject
		{
/*			public:
				virtual HRESULT STDMETHODCALLTYPE GetDesc( 
					_Out_  DXGI_SURFACE_DESC *pDesc) = 0;
        
				virtual HRESULT STDMETHODCALLTYPE Map( 
					_Out_  DXGI_MAPPED_RECT *pLockedRect,
					UINT MapFlags) = 0;
        
				virtual HRESULT STDMETHODCALLTYPE Unmap( void) = 0;*/
		};

		public interface class ISurface1 : public ISurface
		{
			public:
/*				virtual HRESULT STDMETHODCALLTYPE GetDC( 
					BOOL Discard,
					_Out_  HDC *phdc) = 0;
        
				virtual HRESULT STDMETHODCALLTYPE ReleaseDC( 
					_In_opt_  RECT *pDirtyRect) = 0;*/
		};

		public interface class ISurface2 : public ISurface1
		{
		public:
/*			virtual HRESULT STDMETHODCALLTYPE GetResource( 
				_In_  REFIID riid,
				_Out_  void **ppParentResource,
				_Out_  UINT *pSubresourceIndex) = 0;*/
		};
	}
}